<template>
    <div class="menu-manager">
        <!-- 页面标题区域 -->
        <div class="page-header">
            <h2>菜单管理</h2>
            <el-tag type="info">共 {{ tableData.length }} 个菜单项</el-tag>
        </div>

        <div class="content-box">
            <!-- 操作栏 -->
            <el-card class="operation-area" shadow="hover">
                <div class="control-btns">
                    <div class="right-btns">
                        <el-button type="primary" plain size="default" @click="exportVisible = true">
                            <el-icon><Download /></el-icon> 导出数据
                        </el-button>
                        <el-button type="primary" plain size="default" @click="openDialog('add')">
                            <el-icon><Plus /></el-icon> 新增菜单项
                        </el-button>
                    </div>
                </div>
            </el-card>

            <!-- 表格区域 -->
            <el-card class="table-card" shadow="hover">
                <el-table ref="multipleTableRef" v-loading="listLoading" :data="tableData"
                     row-key="id" tooltip-effect="dark" style="width: 100%"
                     size="default" border default-expand-all>
                    <el-table-column prop="id" label="ID" width="80" align="center"></el-table-column>
                    <el-table-column prop="name" label="菜单名称" min-width="120"></el-table-column>
                    <el-table-column prop="path" label="菜单路径" min-width="120"></el-table-column>
                    <el-table-column label="菜单图标" width="100" align="center">
                      <template #default="scope">
                        <!-- 1. 列表图标：使用 component 组件渲染 -->
                        <component
                            :is="getIconComponent(scope.row.icon)"
                            style="font-size: 16px;width: 16px;text-align: center !important;height: 16px;"
                        ></component>
                      </template>
                    </el-table-column>
                    <el-table-column prop="description" label="菜单描述" min-width="150"></el-table-column>
                    <el-table-column prop="pagePath" label="页面路径" min-width="120"></el-table-column>
                    <el-table-column prop="role" label="菜单分配" min-width="120">
                        <template #default="scope">
                            <el-tag v-if="scope.row.role.includes('SUPER_ADMIN')" size="small" type="danger">超级管理员</el-tag>
                            <el-tag v-if="scope.row.role.includes('ADMIN')&&scope.row.role!='SUPER_ADMIN'" size="small" type="warning">管理员</el-tag>
                            <el-tag v-if="scope.row.role.includes('MERCHANT')" size="small" type="success">商户</el-tag>
                            <el-tag v-if="scope.row.role.includes('USER')" size="small" type="info">普通用户</el-tag>
                        </template>
                    </el-table-column>
                    <el-table-column prop="sortNum" label="排序" width="80" align="center"></el-table-column>
                    <el-table-column label="操作" width="350" align="center" fixed="right">
                        <template #default="scope">
                            <el-button v-if="!scope.row.pid && !scope.row.path"
                                     size="small" type="success" plain
                                     @click="addChildMenu(scope.row.id)">
                                <el-icon><Plus /></el-icon> 子菜单
                            </el-button>
                            <el-button size="small" type="primary" plain @click="openDialog('edit', scope.row)">
                                <el-icon><Edit /></el-icon> 编辑
                            </el-button>
                            <el-button size="small" type="danger" plain @click="handleDelete(scope.$index, scope.row)">
                                <el-icon><Delete /></el-icon> 删除
                            </el-button>
                        </template>
                    </el-table-column>
                </el-table>
            </el-card>

            <!-- 新增/编辑菜单项 弹出框 -->
            <el-dialog :title="dialogMode === 'add' ? '新增菜单项' : '修改菜单项'" v-model="formVisible" width="500px"
                :close-on-click-modal="false">
                <el-form :model="dialogForm" :rules="formRules" ref="dialogFormRef" label-width="100px">
                    <el-form-item label="菜单名称" prop="name">
                        <el-input v-model="dialogForm.name" placeholder="请输入菜单名称"></el-input>
                    </el-form-item>
                    <el-form-item label="菜单路径">
                        <el-input v-model="dialogForm.path" placeholder="请输入菜单路径"></el-input>
                    </el-form-item>
                    <el-form-item label="菜单图标" prop="icon">
                        <el-select v-model="dialogForm.icon" filterable placeholder="请选择图标" style="width: 100%;">
                            <el-option v-for="dict in iconDict" :key="dict.itemKey" :label="dict.itemKey"
                                :value="dict.itemValue">
                              <component
                                  :is="getIconComponent(dict.itemValue)"
                                  style="font-size: 14px; margin-right: 8px;width: 16px;"
                              ></component>
                              {{ dict.itemKey }}
                            </el-option>
                        </el-select>
                    </el-form-item>
                    <el-form-item label="页面路径">
                        <el-input v-model="dialogForm.pagePath" placeholder="请输入页面路径"></el-input>
                    </el-form-item>
                    <el-form-item label="排序" prop="sortNum">
                        <el-input-number v-model="dialogForm.sortNum" :min="0" controls-position="right" style="width: 100%;"></el-input-number>
                    </el-form-item>
                    <el-form-item label="菜单分配" prop="role">
                        <el-checkbox-group v-model="checkList">
                            <el-checkbox label="超级管理员" key="SUPER_ADMIN"></el-checkbox>
                            <el-checkbox label="管理员" key="ADMIN"></el-checkbox>
                            <el-checkbox label="商户" key="MERCHANT"></el-checkbox>
                            <el-checkbox label="普通用户" key="USER"></el-checkbox>
                        </el-checkbox-group>
                    </el-form-item>
                    <el-form-item label="描述">
                        <el-input type="textarea" v-model="dialogForm.description" placeholder="请输入描述信息"></el-input>
                    </el-form-item>
                </el-form>
                <template #footer>
                    <div class="dialog-footer">
                        <el-button @click="formVisible = false" plain>取 消</el-button>
                        <el-button type="primary" :loading="isSubmit" @click="handleSave" plain>确 定</el-button>
                    </div>
                </template>
            </el-dialog>

            <!-- 导出数据 弹出栏 -->
            <el-dialog title="导出数据" v-model="exportVisible" width="400px" :close-on-click-modal="false">
                <div class="export-data">
                    <el-button type="primary" plain @click="exportTable('xlsx')">
                        <el-icon><Document /></el-icon> EXCEL格式
                    </el-button>
                    <el-button type="primary" plain @click="exportTable('csv')">
                        <el-icon><Document /></el-icon> CSV格式
                    </el-button>
                    <el-button type="primary" plain @click="exportTable('txt')">
                        <el-icon><Document /></el-icon> TXT格式
                    </el-button>
                </div>
                <div class="hints">提示：请选择要导出数据的格式</div>
            </el-dialog>
        </div>
    </div>
</template>

<script setup>
import { ref, reactive, onMounted } from 'vue'
import { ElMessage, ElMessageBox, ElCard, ElForm, ElFormItem, ElInput, ElTag, ElButton, ElTable, ElTableColumn, ElDialog, ElIcon, ElSelect, ElOption, ElCheckboxGroup, ElCheckbox, ElInputNumber } from 'element-plus'
import { Download, Plus, Edit, Delete, Document } from '@element-plus/icons-vue'
import excel from '../utils/excel.js'
import Request from '../utils/request.js'

// 表单引用
const multipleTableRef = ref()
const dialogFormRef = ref()

// 响应式数据
const listLoading = ref(true)
const formLabelWidth = ref('80px')
const iconDict = ref({})
const checkList = ref([])
const total = ref(0)
const tableData = ref([])
const formVisible = ref(false)
const dialogMode = ref('add') // 'add' or 'edit'
const exportVisible = ref(false)
const isSubmit = ref(false)

const dialogForm = reactive({
    name: undefined,
    description: undefined,
})

// 表单校验规则
const formRules = reactive({
    // 验证规则
    name: [
        { required: true, message: '请填写菜单名称', trigger: 'blur' }
    ],
    sortNum: [
        { required: true, message: '排序不能为空', trigger: 'blur' },
    ],
    icon: [
        { required: true, message: '请选择菜单图标', trigger: 'change' }
    ]
})

// 处理删除
const handleDelete = (index, row) => {
    console.log(index, row)
    ElMessageBox.confirm('此操作将删除选中数据, 是否继续?', '提示', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
        type: 'warning'
    }).then(() => {
        Request.delete("/menu/deleteById/" + row.id).then(response => {
            if (response.code == 0) {
                ElMessage({
                    type: 'success',
                    message: '删除成功!'
                })
                fetchData()
            } else {
                ElMessage({
                    type: 'error',
                    message: '删除失败!'
                })
            }
        });

    }).catch(() => {
        ElMessage({
            type: 'info',
            message: '已取消删除'
        })
    })
}

// 添加子菜单
const addChildMenu = (pid) => {
    dialogMode.value = 'add';
    formVisible.value = true;
    Object.assign(dialogForm, {
        pid: pid,
        name: '',
        path: '',
        icon: '',
        pagePath: '',
        description: '',
        sortNum: 0
    });
    checkList.value = [];
    loadIconList();
}

// 加载图标列表
const loadIconList = () => {
    Request.get("/dictitem/findByType", {
        params: {
            code: "icon"
        }
    }).then(response => {
        if (response.code === '0') {
            iconDict.value = response.data;
            console.log(iconDict.value)
        } else {
            ElMessage({
                type: 'error',
                message: '图标列表失败!'
            })
        }
    });
}

// 获取数据列表
const fetchData = async () => {
    listLoading.value = true
    try {
        const res = await Request.get("/menu/findAll")
        if (res.code === '0') {
            tableData.value = res.data || []
            total.value = tableData.value.length
        } else {
            ElMessage.error(res.msg || '获取菜单列表失败')
        }
    } catch (error) {
        console.error('获取菜单列表失败:', error)
        ElMessage.error('获取菜单列表失败')
    } finally {
        listLoading.value = false
    }
}

// 打开对话框
const openDialog = (mode, row = {}) => {
    dialogMode.value = mode;
    formVisible.value = true;
    loadIconList();
    if (mode === 'edit') {
        Object.assign(dialogForm, JSON.parse(JSON.stringify(row)));
        checkList.value = formatRolesToChinese(row.role);
    } else {
        Object.assign(dialogForm, {});
        checkList.value = [];
    }
}

// 保存新增/编辑数据
const handleSave = () => {
    dialogForm.role = formatRolesToEnglish(checkList.value);
    dialogFormRef.value.validate(valid => {
        if (valid) {
            const saveData = {
                ...dialogForm,
                pid: dialogForm.pid || null
            };

            const request = dialogMode.value === 'add'
                ? Request.post("/menu/save", saveData)
                : Request.put("/menu/" + dialogForm.id, saveData);

            request.then(response => {
                if (response.code === '0') {
                    ElMessage({
                        showClose: true,
                        message: dialogMode.value === 'add' ? '添加成功' : '更新成功',
                        type: 'success',
                    });
                    formVisible.value = false;
                    fetchData();
                } else {
                    ElMessage({
                        showClose: true,
                        message: response.msg || (dialogMode.value === 'add' ? '添加失败' : '更新失败'),
                        type: 'error',
                    });
                }
            }).catch(error => {
                console.error('保存失败:', error);
                ElMessage.error('操作失败，请重试');
            }).finally(() => {
                isSubmit.value = false;
            });
        } else {
            isSubmit.value = false;
        }
    });
}

const getIconComponent = (iconName) => {
  return iconName
}

// 导出数据
const exportTable = (type) => {
    if (tableData.value.length) {
        const params = {
            header: ['菜单ID', '菜单名', '菜单路径', '菜单图标', '描述', '父级菜单ID', '页面路径', '排序', '菜单所属角色'], // 修改表头以匹配类属性
            key: ['id', 'name', 'path', 'icon', 'description', 'pid', 'pagePath', 'sortNum', 'role'], // 修改key以匹配类属性
            data: tableData.value, // 假定tableData.value已经是格式化好的数组，每个元素是一个菜单对象
            autoWidth: true,
            fileName: '菜单数据表',
            bookType: type
        }
        excel.exportDataToExcel(params)
        exportVisible.value = false
    }
}

// 格式化角色为中文
const formatRolesToChinese = (role) => {
    const roleMap = {
        USER: '普通用户',
        MERCHANT: '商户',
        ADMIN: '管理员',
        SUPER_ADMIN: '超级管理员'
    };

    // 如果role为空，则返回空数组
    if (!role) {
        return [];
    }

    // 将角色字符串按照逗号分割成数组，并去除单引号
    const roles = role.split(',').map(singleRole => singleRole.trim().replace(/'/g, ''));

    // 使用 map 方法将数组中的每个英文角色转换为中文角色
    const chineseRoles = roles.map(singleRole => roleMap[singleRole]);

    // 过滤掉未找到映射的项（如果英文角色不在roleMap中）
    const validChineseRoles = chineseRoles.filter(role => role !== undefined);

    // 返回中文角色数组
    return validChineseRoles;
}

// 格式化角色为英文
const formatRolesToEnglish = (chineseRoles) => {
    const roleMap = {
        普通用户: 'USER',
        商户: 'MERCHANT',
        管理员: 'ADMIN',
        超级管理员: 'SUPER_ADMIN'
    };

    // 如果输入数组为空，则返回空字符串
    if (!chineseRoles || chineseRoles.length === 0) {
        return '';
    }

    // 使用 map 方法将数组中的每个中文角色转换为英文角色
    const englishRoles = chineseRoles.map(singleRole => roleMap[singleRole.trim()]);

    // 使用 join 方法将转换后的英文角色数组连接成一个逗号分隔的字符串
    return englishRoles.join(',');
}

// 生命周期钩子
onMounted(() => {
    fetchData()
    loadIconList()
})
</script>

<style lang="less" scoped>
.menu-manager {
    padding: 24px;
    background-color: #f0f2f5;
    min-height: calc(100vh - 60px);
}

.page-header {
    display: flex;
    align-items: center;
    margin-bottom: 24px;

    h2 {
        font-size: 24px;
        font-weight: 500;
        color: #1f2f3d;
        margin: 0;
        margin-right: 15px;
    }
}

.operation-area {
    background: white;
    border-radius: 8px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
    margin-bottom: 24px;
}

.table-card {
    border-radius: 8px;
    box-shadow: 0 1px 4px rgba(0, 0, 0, 0.05);
}

.control-btns {
    display: flex;
    justify-content: flex-end;
    align-items: center;

    .right-btns {
        display: flex;
        gap: 10px;
    }
}

:deep(.el-table) {
    border-radius: 8px;
    overflow: hidden;
    box-shadow: none;

    th {
        background-color: #fafafa;
        font-weight: 500;
        color: #1f2f3d;
        padding: 12px 0;
    }

    td {
        padding: 12px 0;
    }
}

.el-tag {
    margin-right: 5px;

    &:last-child {
        margin-right: 0;
    }
}

:deep(.el-dialog) {
    border-radius: 12px;
    overflow: hidden;
    box-shadow: 0 8px 32px rgba(0, 0, 0, 0.1);

    .el-dialog__header {
        padding: 24px;
        border-bottom: 1px solid #ebeef5;
        margin: 0;
    }

    .el-dialog__title {
        font-size: 18px;
        font-weight: 500;
        color: #1f2f3d;
    }

    .el-dialog__body {
        padding: 32px 24px;
    }

    .el-dialog__footer {
        padding: 16px 24px;
        border-top: 1px solid #ebeef5;
    }
}

.export-data {
    display: flex;
    justify-content: space-around;
    margin-bottom: 20px;
}

.hints {
    text-align: center;
    color: #909399;
    font-size: 12px;
}
</style>